package com.mlethe.library.utils.device;

import android.Manifest;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.telephony.TelephonyManager;

import androidx.core.app.ActivityCompat;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.util.UUID;

public class DeviceUtil {

    /**
     * 有线连接
     */
    public static final int NETWORK_ETHERNET = -2;

    /**
     * wifi连接
     */
    public static final int NETWORK_WIFI = -1;

    /**
     * 没有网络连接
     */
    public static final int NETWORK_NONE = 0;

    /**
     * 手机网络数据连接
     */
    public static final int NETWORK_MOBILE = 1;

    /**
     * 2G 网络
     */
    public static final int NETWORK_2G = 2;

    /**
     * 3G 网络
     */
    public static final int NETWORK_3G = 3;

    /**
     * 4G 网络
     */
    public static final int NETWORK_4G = 4;

    /**
     * 5G 网络
     */
    public static final int NETWORK_5G = 5;

    /**
     * 获取当前网络连接类型
     * <p>
     * GPRS    2G(2.5) General Packet Radia Service 114kbps
     * EDGE    2G(2.75G) Enhanced Data Rate for GSM Evolution 384kbps
     * UMTS    3G WCDMA 联通3G Universal MOBILE Telecommunication System 完整的3G移动通信技术标准
     * CDMA    2G 电信 Code Division Multiple Access 码分多址
     * EVDO_0  3G (EVDO 全程 CDMA2000 1xEV-DO) Evolution - Data Only (Data Optimized) 153.6kps - 2.4mbps 属于3G
     * EVDO_A  3G 1.8mbps - 3.1mbps 属于3G过渡，3.5G
     * 1xRTT   2G CDMA2000 1xRTT (RTT - 无线电传输技术) 144kbps 2G的过渡,
     * HSDPA   3.5G 高速下行分组接入 3.5G WCDMA High Speed Downlink Packet Access 14.4mbps
     * HSUPA   3.5G High Speed Uplink Packet Access 高速上行链路分组接入 1.4 - 5.8 mbps
     * HSPA    3G (分HSDPA,HSUPA) High Speed Packet Access
     * IDEN    2G Integrated Dispatch Enhanced Networks 集成数字增强型网络 （属于2G，来自维基百科）
     * EVDO_B  3G EV-DO Rev.B 14.7Mbps 下行 3.5G
     * LTE     4G Long Term Evolution FDD-LTE 和 TDD-LTE , 3G过渡，升级版 LTE Advanced 才是4G
     * EHRPD   3G CDMA2000向LTE 4G的中间产物 Evolved High Rate Packet Data HRPD的升级
     * HSPAP   3G HSPAP 比 HSDPA 快些
     *
     * @return
     */
    public static int getNetworkState(Context context) {
        //获取系统的网络服务
        ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connManager == null) {
            return NETWORK_NONE;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 6.0以上
            Network networks = connManager.getActiveNetwork();
            NetworkCapabilities networkCapabilities = connManager.getNetworkCapabilities(networks);
            if (networkCapabilities != null) {
                if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                    // wifi
                    return NETWORK_WIFI;
                } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                    // 手机网络
                    if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                        // 未授权
                        return getMobileNetworkState(connManager);
                    }
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        // 7.0以上
                        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
                        if (telephonyManager != null) {
                            switch (telephonyManager.getDataNetworkType()) {
                                case TelephonyManager.NETWORK_TYPE_GPRS:
                                case TelephonyManager.NETWORK_TYPE_CDMA:
                                case TelephonyManager.NETWORK_TYPE_EDGE:
                                case TelephonyManager.NETWORK_TYPE_1xRTT:
                                case TelephonyManager.NETWORK_TYPE_IDEN:
                                    return NETWORK_2G;
                                case TelephonyManager.NETWORK_TYPE_EVDO_A:
                                case TelephonyManager.NETWORK_TYPE_UMTS:
                                case TelephonyManager.NETWORK_TYPE_EVDO_0:
                                case TelephonyManager.NETWORK_TYPE_HSDPA:
                                case TelephonyManager.NETWORK_TYPE_HSUPA:
                                case TelephonyManager.NETWORK_TYPE_HSPA:
                                case TelephonyManager.NETWORK_TYPE_EVDO_B:
                                case TelephonyManager.NETWORK_TYPE_EHRPD:
                                case TelephonyManager.NETWORK_TYPE_HSPAP:
                                case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
                                    return NETWORK_3G;
                                case TelephonyManager.NETWORK_TYPE_LTE:
                                    return NETWORK_4G;
                                case TelephonyManager.NETWORK_TYPE_NR:
                                    return NETWORK_5G;
                            }
                        }
                    } else {
                        return getMobileNetworkState(connManager);
                    }
                    return NETWORK_MOBILE;
                } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
                    // 有线(以太网)
                    return NETWORK_ETHERNET;
                }
            } else {
                return NETWORK_NONE;
            }
        } else {
            // 获取当前网络类型，如果为空，返回无网络
            NetworkInfo activeNetInfo = connManager.getActiveNetworkInfo();
            if (activeNetInfo == null || !activeNetInfo.isAvailable()) {
                return NETWORK_NONE;
            }
            if (activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                // wifi
                return NETWORK_WIFI;
            } else if (activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
                // 数据网络，判断当前连接的是运营商的哪种网络2g、3g、4g等
                return getMobileNetworkState(connManager);
            } else if (activeNetInfo.getType() == ConnectivityManager.TYPE_ETHERNET) {
                // 有线(以太网)
                return NETWORK_ETHERNET;
            }
        }
        return NETWORK_NONE;
    }

    /**
     * 获取手机数据网络类型
     *
     * @param connManager
     * @return
     */
    private static int getMobileNetworkState(ConnectivityManager connManager) {
        if (connManager == null) {
            return NETWORK_NONE;
        }
        NetworkInfo networkInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
        if (networkInfo == null) {
            return NETWORK_NONE;
        }
        NetworkInfo.State state = networkInfo.getState();
        String subtypeName = networkInfo.getSubtypeName();
        if (null != state) {
            if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING) {
                switch (networkInfo.getSubtype()) {
                    case TelephonyManager.NETWORK_TYPE_GPRS:
                    case TelephonyManager.NETWORK_TYPE_CDMA:
                    case TelephonyManager.NETWORK_TYPE_EDGE:
                    case TelephonyManager.NETWORK_TYPE_1xRTT:
                    case TelephonyManager.NETWORK_TYPE_IDEN:
                        return NETWORK_2G;
                    case TelephonyManager.NETWORK_TYPE_EVDO_A:
                    case TelephonyManager.NETWORK_TYPE_UMTS:
                    case TelephonyManager.NETWORK_TYPE_EVDO_0:
                    case TelephonyManager.NETWORK_TYPE_HSDPA:
                    case TelephonyManager.NETWORK_TYPE_HSUPA:
                    case TelephonyManager.NETWORK_TYPE_HSPA:
                    case TelephonyManager.NETWORK_TYPE_EVDO_B:
                    case TelephonyManager.NETWORK_TYPE_EHRPD:
                    case TelephonyManager.NETWORK_TYPE_HSPAP:
                        return NETWORK_3G;
                    case TelephonyManager.NETWORK_TYPE_LTE:
                        return NETWORK_4G;
                    case TelephonyManager.NETWORK_TYPE_NR:
                        return NETWORK_5G;
                    default:
                        //中国移动 联通 电信 三种3G制式
                        if ("TD-SCDMA".equalsIgnoreCase(subtypeName) || "WCDMA".equalsIgnoreCase(subtypeName) || "CDMA2000".equalsIgnoreCase(subtypeName)) {
                            return NETWORK_3G;
                        } else {
                            return NETWORK_MOBILE;
                        }
                }
            }
        }
        return NETWORK_NONE;
    }

    /**
     * 检测当前网络是否可用
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    public static boolean isNetworkEnabled(Context context) {
        ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Network network = connManager.getActiveNetwork();
            NetworkCapabilities networkCapabilities = connManager.getNetworkCapabilities(network);
            if (networkCapabilities != null) {
                if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                    // wifi
                    return true;
                } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                    // 手机数据网络
                    return true;
                } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
                    // 有线(以太网)
                    return true;
                }
            }
        } else {
            NetworkInfo networkInfo = connManager.getActiveNetworkInfo();
            if (networkInfo == null || !networkInfo.isAvailable()) {
                return false;
            }
            NetworkInfo.State state = networkInfo.getState();
            if (state == null) {
                return false;
            }
            if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取ip地址
     *
     * @param context
     * @return
     */
    public static String getIpAddress(Context context) {
        ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connManager == null) {
            return null;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Network networks = connManager.getActiveNetwork();
            LinkProperties linkProperties = connManager.getLinkProperties(networks);
            if (linkProperties != null) {
                for (LinkAddress linkAddress : linkProperties.getLinkAddresses()) {
                    InetAddress address = linkAddress.getAddress();
                    if (address instanceof Inet4Address) {
                        return address.getHostAddress();
                    }
                }
            }
        } else {
            NetworkInfo info = connManager.getActiveNetworkInfo();
            if (info != null && info.isConnected()) {
                if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
                    //3G/4G网络
                    try {
                        for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                            NetworkInterface intf = en.nextElement();
                            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                                InetAddress inetAddress = enumIpAddr.nextElement();
                                if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                                    return inetAddress.getHostAddress();
                                }
                            }
                        }
                    } catch (SocketException e) {
                        return null;
                    }
                } else if (info.getType() == ConnectivityManager.TYPE_WIFI) {
                    // wifi
                    WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
                    WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                    return intIp2StringIp(wifiInfo.getIpAddress());
                }
            } else {
                return null;
            }
        }
        return null;
    }

    /**
     * 将得到的int类型的IP转换为String类型
     *
     * @param ip
     * @return
     */
    private static String intIp2StringIp(int ip) {
        return (ip & 0xFF) + "." +
                ((ip >> 8) & 0xFF) + "." +
                ((ip >> 16) & 0xFF) + "." +
                (ip >> 24 & 0xFF);
    }

    /**
     * 获取mac
     * <p>
     * 需要加入 android.permission.INTERNET 权限
     *
     * @param context
     * @return
     */
    @SuppressLint("HardwareIds")
    public static String getMacAddress(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            try {
                // 获取本机器所有的网络接口
                Enumeration<NetworkInterface> enumeration = NetworkInterface.getNetworkInterfaces();
                while (enumeration.hasMoreElements()) {
                    NetworkInterface networkInterface = enumeration.nextElement();
                    //获取硬件地址，一般是MAC
                    byte[] arrayOfByte = networkInterface.getHardwareAddress();
                    if (arrayOfByte == null || arrayOfByte.length == 0) {
                        continue;
                    }

                    StringBuilder stringBuilder = new StringBuilder();
                    for (byte b : arrayOfByte) {
                        //格式化为：两位十六进制加冒号的格式，若是不足两位，补0
                        stringBuilder.append(String.format("%02X:", new Object[]{Byte.valueOf(b)}));
                    }
                    if (stringBuilder.length() > 0) {
                        //删除后面多余的冒号
                        stringBuilder.deleteCharAt(stringBuilder.length() - 1);
                    }
                    String str = stringBuilder.toString();
                    // wlan0:无线网卡 eth0：以太网卡
                    if (networkInterface.getName().equals("wlan0")) {
                        return str;
                    }
                }
            } catch (SocketException e) {
                e.printStackTrace();
                return null;
            }
        }
        try {
            WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            if (wifiInfo != null) {
                return wifiInfo.getMacAddress();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Pseudo-Unique ID, 这个在任何Android手机中都有效
     * 有一些特殊的情况，一些如平板电脑的设置没有通话功能，或者你不愿加入READ_PHONE_STATE许可。而你仍然想获得唯
     * 一序列号之类的东西。这时你可以通过取出ROM版本、制造商、CPU型号、以及其他硬件信息来实现这一点。这样计算出
     * 来的ID不是唯一的（因为如果两个手机应用了同样的硬件以及Rom 镜像）。但应当明白的是，出现类似情况的可能性基
     * 本可以忽略。大多数的Build成员都是字符串形式的，我们只取他们的长度信息。我们取到13个数字，并在前面加上“35
     * ”。这样这个ID看起来就和15位IMEI一样了。
     *
     * @return PesudoUniqueID
     */
    @SuppressLint("MissingPermission")
    public static String getPesudoUniqueId() {
        //we make this look like a valid IMEI
        //使用硬件信息拼凑出来的15位号码
        return  "35" +
                Build.BOARD.length() % 10 +
                Build.BRAND.length() % 10 +
                Build.CPU_ABI.length() % 10 +
                Build.DEVICE.length() % 10 +
                Build.DISPLAY.length() % 10 +
                Build.HOST.length() % 10 +
                Build.ID.length() % 10 +
                Build.MANUFACTURER.length() % 10 +
                Build.MODEL.length() % 10 +
                Build.PRODUCT.length() % 10 +
                Build.TAGS.length() % 10 +
                Build.TYPE.length() % 10 +
                Build.USER.length() % 10; //13 digits
    }

    /**
     * 获取指定字段信息
     *
     * @return
     */
    public static String getDeviceInfo() {
        return "\n主板：" + Build.BOARD +
                "\n系统启动程序版本号：" + Build.BOOTLOADER +
                "\n系统定制商：" + Build.BRAND +
                "\ncpu指令集：" + Build.CPU_ABI +
                "\ncpu指令集2：" + Build.CPU_ABI2 +
                "\n设置参数：" + Build.DEVICE +
                "\n显示屏参数：" + Build.DISPLAY +
                "\n无线电固件版本：" + Build.getRadioVersion() +
                "\n硬件识别码：" + Build.FINGERPRINT +
                "\n硬件名称：" + Build.HARDWARE +
                "\nHOST:" + Build.HOST +
                "\n修订版本列表：" + Build.ID +
                "\n硬件制造商：" + Build.MANUFACTURER +
                "\n版本：" + Build.MODEL +
                "\n硬件序列号：" + Build.SERIAL +
                "\n手机制造商：" + Build.PRODUCT +
                "\n描述Build的标签：" + Build.TAGS +
                "\nTIME:" + Build.TIME +
                "\nbuilder类型：" + Build.TYPE +
                "\nUSER:" + Build.USER;
    }

    /**
     * 只在有蓝牙的设备上运行。并且要加入android.permission.BLUETOOTH 权限.Returns: 43:25:78:50:93:38 .
     * 蓝牙没有必要打开，也能读取。
     *
     * @return
     */
    @SuppressLint({"MissingPermission", "HardwareIds"})
    public static String getBTMACAddress() {
        try {
            BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
            return bluetoothAdapter.getAddress();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取唯一标识
     *
     * @return
     */
    public static String getUniqueId(Context context) {
        String str = getPesudoUniqueId() + getMacAddress(context);
        try {
            // compute md5
            MessageDigest m = MessageDigest.getInstance("MD5");
            m.update(str.getBytes(), 0, str.length());
            // get md5 bytes
            byte[] md5Data = m.digest();
            // create a hex string
            StringBuilder uniqueId = new StringBuilder();
            for (byte md5Datum : md5Data) {
                int b = (0xFF & md5Datum);
                // if it is a single digit, make sure it have 0 in front (proper padding)
                if (b <= 0xF) {
                    uniqueId.append("0");
                }
                // add number to string
                uniqueId.append(Integer.toHexString(b));
            }   // hex string to uppercase
            return uniqueId.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

}
